<script setup>
import {onMounted, ref, toRef} from "vue";
import {
  createDirectory, deleteFileOrDir,
  loadAllFileAndFolderInfo,
  moveFileOrDir,
  readDir, readTextFile,
  renameFileOrDir,
  writeTextFile
} from "@/util/file";
import {getPomObj} from "@/util/java/mavenPom";
import { ElLoading } from 'element-plus'

const formInfo = [
  {label: '组', key: 'groupId'},
  {label: '工件', key: 'artifactId'},
]

const projectInfo = defineModel();
const javaInfo = toRef(projectInfo.value, 'java')
const oldJavaInfo = ref({})

const rootPom = ref()

onMounted(async () => {
  projectInfo.value.fileList = await loadAllFileAndFolderInfo(projectInfo.value.path)

  rootPom.value = await getPomObj(projectInfo.value.fileList)

  oldJavaInfo.value.groupId = rootPom.value.pom.groupId
  oldJavaInfo.value.artifactId = rootPom.value.pom.artifactId
  javaInfo.value.groupId = rootPom.value.pom.groupId
  javaInfo.value.artifactId = rootPom.value.pom.artifactId


})

/**
 * 更新项目中的POM配置信息
 *
 * 该函数会根据用户输入的groupId和artifactId更新项目中的所有pom.xml文件，
 * 并根据需要重命名模块目录。
 *
 * @returns {Promise<void>} 无返回值
 */
async function changePom() {

  // 创建模块映射表，用于后续目录重命名
  const modulesMap = {}
  rootPom.value.pom.modules.forEach((item, index) => modulesMap[index] = item)

  // 更新根项目的groupId和artifactId
  rootPom.value.pom.groupId = javaInfo.value.groupId
  rootPom.value.pom.artifactId = javaInfo.value.artifactId

  // 更新模块映射表，将索引映射为实际的模块名称
  rootPom.value.pom.modules.forEach((item, index) => modulesMap[modulesMap[index]] = item)

  // 更新所有子模块的groupId和artifactId
  rootPom.value.children.forEach(item => {
    item.pom.groupId = javaInfo.value.groupId
    item.pom.artifactId = modulesMap[item.pom.artifactId]
  })

  // 获取所有Java项目的POM配置并更新文件
  const pomList = rootPom.value.getAllJavaPom()
  for (let i = 0; i < pomList.length; i++) {
    const item = pomList[i]

    // 将更新后的POM配置写入文件
    await writeTextFile(item.path, item.pom.toXml())

    const list = item.path.split('/')
    // 检查是否需要重命名目录
    if (modulesMap[list[list.length - 2]]) {
      // 构建原目录路径
      let pathStr = ''
      for (let j = 0; j < list.length - 2; j++) {
        pathStr += list[j] + '/'
      }
      pathStr += list[list.length - 2]
      // 重命名目录
      await renameFileOrDir(pathStr, modulesMap[list[list.length - 2]])
    }
  }

  // 重新加载项目文件列表和POM对象
  projectInfo.value.fileList = await loadAllFileAndFolderInfo(projectInfo.value.path)
  rootPom.value = await getPomObj(projectInfo.value.fileList)
}

/**
 * 修改Java项目的包路径和目录结构
 *
 * 该函数会根据新的groupId修改项目中的Java包路径：
 * 1. 创建新的包目录结构
 * 2. 移动原有的Java文件到新目录
 * 3. 删除旧的包目录
 * 4. 更新所有Java文件中的包声明
 */
async function changeJavaPathAndPackage() {

  const oldGroupIdDirList = oldJavaInfo.value.groupId.split('.')
  const oldGroupIdDirPath = oldGroupIdDirList.join('/')
  const newGroupIdDirList = javaInfo.value.groupId.split('.')
  const newGroupIdDirPath = newGroupIdDirList.join('/')

  // 处理每个模块的源码目录
  let pathList = rootPom.value.children.map(item => item.path.replace('/pom.xml', '/src/main/java'))
  for (let i = 0; i < pathList.length; i++) {
    const oldPath = pathList[i] + '/' + oldGroupIdDirPath
    const newPath = pathList[i] + '/' + newGroupIdDirPath
    await createDirectory(newPath)

    const fileList = await readDir(oldPath)
    for (let j = 0; j < fileList.length; j++) {
      await moveFileOrDir(fileList[j].path, newPath)
    }

    await deleteFileOrDir(pathList[i] + '/' + oldGroupIdDirList[0])
  }

  // 重新加载项目文件列表和POM对象
  projectInfo.value.fileList = await loadAllFileAndFolderInfo(projectInfo.value.path)
  rootPom.value = await getPomObj(projectInfo.value.fileList)

  // 更新所有Java文件中的包声明
  pathList = rootPom.value.children.map(item => item.path.replace('/pom.xml', '/src/main'))
  const filePathList = projectInfo.value.fileList
      .filter(item => {
        for (let i = 0; i < pathList.length; i++) {
          if (item.path.includes(pathList[i]) && item.type === 'file') {
            return true
          }
        }
      }).map(item => item.path)
  for (let i = 0; i < filePathList.length; i++) {
    let fileText = await readTextFile(filePathList[i])
    if(fileText.includes(oldJavaInfo.value.groupId)){
      fileText = fileText.replaceAll(oldJavaInfo.value.groupId, javaInfo.value.groupId)
      await writeTextFile(filePathList[i], fileText)
    }
  }

}

async function saveAndRun() {
  const loadingInstance = ElLoading.service({ fullscreen: true })
  //更改pom
  await changePom()
  //更改java文件中文件夹的名称和包路径
  await changeJavaPathAndPackage()
  loadingInstance.close()
}
</script>

<template>
  <el-form class="project-form" label-width="auto" label-position="left">
    <template v-for="item in formInfo" :key="item.key">
      <el-form-item :label="item.label">
        <el-input v-model="javaInfo[item.key]"/>
      </el-form-item>
    </template>
    <el-button type="primary" @click="saveAndRun">保存</el-button>
  </el-form>
</template>

<style scoped lang="scss">
.project-form {
  max-width: 600px;
}
</style>